// Copyright (c) 2020 Presto Labs Pte. Ltd.
// Author: donggu

#include <cxxopts.hpp>

#include "coin/proto/coin_order_gateway.pb.h"
#include "coin2/app/driver.h"
#include "coin2/base/config/app_config.h"
#include "coin2/base/config/args.h"
#include "coin2/base/log.h"
#include "coin2/base/time.h"
#include "coin2/exchange/base/feed/update.h"
#include "coin2/strategy/strategy.h"

using namespace coin2::exchange::base::symbology;
using namespace coin2::base::config;
using namespace coin2::exchange::feed;
using namespace coin2::app;
using coin2::exchange::base::feed::FeedUpdate;
using coin2::exchange::base::order::OrderUpdate;

class BackflowCheckStrategy : public ::coin2::strategy::IStrategy {
 public:
  void onTradeFeed(const FeedUpdate& upd) override {
    topics_++;
    if (upd.timestamp() < last_topic_ts_) {
      backflow_++;
      printf(
          "[backflow found] last topic ts %lu > current topic ts %lu\n",
          last_topic_ts_,
          upd.timestamp());
    }
    last_topic_ts_ = upd.timestamp();
  }
  void onBookFeed(const FeedUpdate& upd) override {
    topics_++;
    if (upd.timestamp() < last_topic_ts_) {
      backflow_++;
      printf(
          "[backflow found] last topic ts %lu > current topic ts %lu\n",
          last_topic_ts_,
          upd.timestamp());
    }
    last_topic_ts_ = upd.timestamp();
  }
  void onAccountInfo(const OrderUpdate& upd) override {
    topics_++;
    if (upd.timestamp() < last_topic_ts_) {
      backflow_++;
      printf(
          "[backflow found] last topic ts %lu > current topic ts %lu\n",
          last_topic_ts_,
          upd.timestamp());
    }
    last_topic_ts_ = upd.timestamp();
  }
  void onAccountOrder(const OrderUpdate& upd) override {
    topics_++;
    if (upd.timestamp() < last_topic_ts_) {
      backflow_++;
      printf(
          "[backflow found] last topic ts %lu > current topic ts %lu\n",
          last_topic_ts_,
          upd.timestamp());
    }
    last_topic_ts_ = upd.timestamp();
  }

  void onOrderLog(const coin::proto::OrderGatewayLog& log) override {
    // log.timestamp
    // std::cout << "onOrderLog: " << log.DebugString() << std::endl;
  }

  int64_t num_topics() { return topics_; }
  int64_t num_backflow() { return backflow_; }

 private:
  int64_t last_topic_ts_ = 0;
  int64_t topics_ = 0;
  int64_t backflow_ = 0;
};

int main(int argc, char* argv[]) {
  google::InitGoogleLogging(argv[0]);
  DriverConfig app;

  cxxopts::Options opt(
      "Feed&Order Backflow Checker",
      "Run the driver and find any topic record with decreasing timestamp");
  AddDriverOptions(&opt);
  AddIntervalOptions(&opt);
  AddProductOptions(&opt);

  auto res = opt.parse(argc, argv);
  ParseDriverOptions(res, &app);
  ParseIntervalOptions(
      res,
      app.mutable_feed()->mutable_common()->mutable_archive()->mutable_interval());
  ParseProductOptions(res, app.mutable_feed());

  BackflowCheckStrategy checker;
  Driver driver(app, &checker);

  printf("Running driver ..\n");
  driver.Run();
  printf("#   Topics: %ld\n", checker.num_topics());
  printf("# Backflow: %ld\n", checker.num_backflow());
  return 0;
}
